VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "ZIPFileUncompress"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit

Public Type tm_unz
    tm_sec As Long                                                              'seconds after the minute - [0,59]
    tm_min As Long                                                              'minutes after the hour - [0,59]
    tm_hour As Long                                                             'hours since midnight - [0,23]
    tm_mday As Long                                                             'day of the month - [1,31]
    tm_mon As Long                                                              'months since January - [0,11]
    tm_year As Long                                                             'years - [1980..2044]
End Type

' unz_global_info structure contain global data about the ZIPfile
' These data comes from the end of central dir
Private Type unz_global_info
    number_entry As Long                                                        'total number of entries in
    'the central dir on this disk
    size_comment As Long                                                        'size of the global comment of the zipfile
End Type

' unz_file_info contain information about a file in the zipfile */
Public Type unz_file_info
    Version As Long                                                             'version made by                 2 bytes
    version_needed As Long                                                      'version needed to extract       2 bytes
    Flag As Long                                                                'general purpose bit flag        2 bytes
    compression_method As Long                                                  'compression method              2 bytes
    dosDate As Long                                                             'last mod file date in Dos fmt   4 bytes
    crc As Long                                                                 'crc-32                          4 bytes
    compressed_size As Long                                                     'compressed size                 4 bytes
    uncompressed_size As Long                                                   'uncompressed size               4 bytes
    size_filename As Long                                                       'filename length                 2 bytes
    size_file_extra As Long                                                     'extra field length              2 bytes
    size_file_comment As Long                                                   'file comment length             2 bytes

    disk_num_start As Long                                                      'disk number start               2 bytes
    internal_fa As Long                                                         'internal file attributes        2 bytes
    external_fa As Long                                                         'external file attributes        4 bytes

    tmu_date As tm_unz
End Type


'public Declare Function Compress Lib "ZLIB.DLL" Alias "compress2" (ByRef DestinationArray As Byte, ByRef DestLen As Long, ByRef SourceArray As Byte, ByVal SourceLen As Long, ByVal CompressionLevel As Long) As Long

' Open a Zip file. path contain the full pathname (by example,
'     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
'     "zlib/zlib113.zip".
'     If the zipfile cannot be opened (file don't exist or in not valid), the
'       return value is NULL.
'     Else, the return value is a unzFile Handle, usable with other function
'       of this unzip package.
Private Declare Function unzOpen Lib "zlib.dll" (ByVal FilePath As String) As Long

'Close a ZipFile opened with unzipOpen.
'If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
' these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
'return UNZ_OK if there is no problem. */
Private Declare Function unzClose Lib "zlib.dll" (ByVal hFile As Long) As Long

' Write info about the ZipFile in the *pglobal_info structure.
' No preparation of the structure is needed
' return UNZ_OK if there is no problem.
Private Declare Function unzGetGlobalInfo Lib "zlib.dll" (ByVal hFile As Long, ByRef pglobal_info As unz_global_info) As Long

' Get Info about the current file
' if pfile_info!=NULL, the *pfile_info structure will contain somes info about
'        the current file
' if szFileName!=NULL, the filemane string will be copied in szFileName
'            (fileNameBufferSize is the size of the buffer)
' if extraField!=NULL, the extra field information will be copied in extraField
'            (extraFieldBufferSize is the size of the buffer).
'            This is the Central-header version of the extra field
' if szComment!=NULL, the comment string of the file will be copied in szComment
'            (commentBufferSize is the size of the buffer)
Private Declare Function unzGetCurrentFileInfo Lib "zlib.dll" (ByVal hFile As Long, _
    ByRef pfile_info As unz_file_info, _
    ByVal szFileName As String, _
    ByVal fileNameBufferSize As Long, _
    ByRef ExtraField As Long, _
    ByVal extraFieldBufferSize As Long, _
    ByVal szComment As String, _
    ByVal commentBufferSize As String) As Long

    ' for reading the content of the current zipfile, you can open it, read data
    ' from it, and close it (you can close it before reading all the file)
    '
    ' Open for reading data the current file in the zipfile.
    ' If there is no error, the return value is UNZ_OK.
Private Declare Function unzOpenCurrentFile Lib "zlib.dll" (ByVal hFile As Long) As Long

'Close the file in zip opened with unzOpenCurrentFile
'Return UNZ_CRCERROR if all the file was read but the CRC is not good
Private Declare Function unzCloseCurrentFile Lib "zlib.dll" (ByVal hFile As Long) As Long
                                       
'Read bytes from the current file (opened by unzOpenCurrentFile)
'buf contain buffer where data must be copied
'len the size of buf.
'return the number of byte copied if somes bytes are copied
'return 0 if the end of file was reached
'return <0 with error code if there is an error
'(UNZ_ERRNO for IO error, or zLib error for uncompress error)
Private Declare Function unzReadCurrentFile Lib "zlib.dll" (ByVal hFile As Long, _
    ByRef Buffer As Byte, _
    ByVal BuffLen As Long) As Long

    'Set the current file of the zipfile to the next file.
    'return UNZ_OK if there is no problem
    'return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
Private Declare Function unzGoToNextFile Lib "zlib.dll" (ByVal hFile As Long) As Long


Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" (ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Private Const BufferSize        As Long = 2048
Private Const MAX_PATH          As Long = 260
Private Const MAX_COMMENT       As Long = 255
Private strFileNameBuff         As String * MAX_PATH
Private szComment               As String * MAX_COMMENT
Private hFile                   As Long
Private buff()                  As Byte

Public Event Uncompressing(FileInfo As unz_file_info)
Public Event StartingUncompressingFile(FileInfo As unz_file_info)
Public Event OnWrtingFileBytes(FileInfo As unz_file_info, Bytes() As Byte)
Public Event EndingUncompressingFile(FileInfo As unz_file_info)
Public Event OnUncompressStart()
Public Event OnUncompressEnd()

Public Sub UnZipTo(ByVal strPath As String, ByVal strZipFile As String)
    Dim strFileName             As String
    Dim tPath                   As String
    Dim info                    As unz_file_info
    Dim i                       As Long
    
    ReDim buff(BufferSize - 1) As Byte
    Dim topFolder As String
    RaiseEvent OnUncompressStart
    hFile = unzOpen(strZipFile)
    If hFile = 0 Then
        Reset
        Err.Raise 5
        Exit Sub
    End If
    On Error GoTo 0
    strPath = Replace(strPath & "\", "\\", "\")
    If Dir(strPath, vbDirectory) = "" Then Call CreateFloder(strPath)
    Do
        i = unzGetCurrentFileInfo(hFile, info, strFileNameBuff, MAX_PATH, 0, 0, szComment, MAX_COMMENT)
        RaiseEvent Uncompressing(info)
        strFileName = left(strFileNameBuff, info.size_filename)
        tPath = strPath
        If InStr(strFileName, "/") > 0 Then
            If InStr(1, strFileName, "/") = Len(strFileName) Then
                topFolder = Mid(strFileName, 1, Len(strFileName) - 1)
            End If
            strFileName = Replace(strFileName, "/", "\")
            tPath = CreateFloder(GetPath(strPath & strFileName))
            strFileName = GetFileName(strFileName)
            
        End If
        
        i = unzOpenCurrentFile(hFile)
        
        If (info.external_fa And &H10) = 0 Then
            If Dir(tPath & strFileName) <> "" Then Kill tPath & strFileName
            Open tPath & strFileName For Binary As #1
            DoEvents
            RaiseEvent StartingUncompressingFile(info)
            Do
                i = unzReadCurrentFile(hFile, buff(0), BufferSize)
                If i = 0 Then Exit Do
                If i < BufferSize Then
                    ReDim tbuff(i - 1) As Byte
                    Call CopyMemory(tbuff(0), buff(0), i)
                    Put #1, , tbuff
                    RaiseEvent OnWrtingFileBytes(info, tbuff)
                Else
                    Put #1, , buff
                    RaiseEvent OnWrtingFileBytes(info, buff)
                End If
            Loop Until (i < BufferSize)
            Close #1
            RaiseEvent EndingUncompressingFile(info)
        End If
        Debug.Assert unzGoToNextFile(hFile) = 0
        
    Loop Until (unzGoToNextFile(hFile) <> 0)
    
    
    i = unzCloseCurrentFile(hFile)
    i = unzClose(hFile)
    RaiseEvent OnUncompressEnd
    
End Sub

Private Function CreateFloder(ByVal strPath As String) As String
    Dim tmpPath As String
    Dim t       As SECURITY_ATTRIBUTES
    Dim i       As Long
    Dim Index   As Integer
    strPath = Replace(strPath & "\", "\\", "\")
    Do
        Index = InStr(Index + 1, strPath, "\")
        tmpPath = left(strPath, Index)
        
        If Dir(tmpPath, vbDirectory) = "" Then
            i = CreateDirectory(tmpPath, t)
        End If
        
    Loop Until (Dir(strPath, vbDirectory) <> "")
    CreateFloder = strPath
End Function

Private Function GetFileName(ByVal strPath As String) As String
    Dim i As Integer
    
    'For i = Len(strPath) To 1 Step -1
    '    If Mid(strPath, i, 1) = "\" Then
    i = InStrRev(strPath, "\")
    
    GetFileName = Right(strPath, Len(strPath) - i)
    '        Exit Function
    '    End If
    'Next i
End Function

Private Function GetPath(ByVal strPath As String) As String
    Dim i As Integer
    
    'For i = Len(strPath) To 1 Step -1
    '    If Mid(strPath, i, 1) = "\" Then
    i = InStrRev(strPath, "\")
    GetPath = left(strPath, i)
    '        Exit Function
    '    End If
    'Next i
End Function


